<!--
 * @Description: 描述列表组件
 * @Author: ZhangHan
 * @Date: 2025-07-04 18:14:30
 * @LastEditTime: 2025-07-10 18:18:50
 * @LastEditors: ZhangHan
-->

<script lang="tsx">
import type { DescriptionProps, DescInstance, DescItem } from "./typing";
import { defineComponent, computed, ref, unref, useAttrs } from "vue";
import { get } from "lodash-es";
import { type CSSProperties } from "vue";
import { ElDescriptions, ElDescriptionsItem } from "element-plus";
import type { DescriptionProps as ElDescriptionProps } from "element-plus";
import { isFunction } from "@/utils/is";

const props = {
  title: { type: String, default: "" },
  size: {
    type: String,
    validator: (v: any) =>
      ["", "large", "default", "small", undefined].includes(v),
    default: "default",
  },
  schema: {
    type: Array as PropType<DescItem[]>, // 描述项的数组
    default: () => [], // 默认为空数组
  },
  data: { type: Object }, // 数据对象，默认没有指定默认值
  border: {
    type: Boolean,
    default: true,
  },
};

export default defineComponent({
  name: "Description",
  props,
  emits: ["register"],
  setup(props, { slots, emit }) {
    const propsRef = ref<Partial<DescriptionProps> | null>(null);
    const attrs = useAttrs();

    //    合并静态props和动态props
    const getMergeProps = computed((): DescriptionProps => {
      return {
        ...props,
        ...(unref(propsRef) as Recordable),
      } as unknown as DescriptionProps;
    });
    console.log(propsRef, "----------------------");

    console.log(getMergeProps, "-----------------------");

    // 获取props
    const getProps = computed(() => {
      const opt = {
        ...unref(getMergeProps),
        // title: undefined,
      };
      return opt as unknown as DescriptionProps;
    });

    // 获取Descriptions组件的props
    const getDescriptionsProps = computed(() => {
      return { ...unref(attrs), ...unref(getProps) } as ElDescriptionProps;
    });

    /**
     * @description:设置desc
     */
    function setDescProps(descProps: Partial<DescriptionProps>): void {
      // Keep the last setDrawerProps
      propsRef.value = {
        ...(unref(propsRef) as Recordable),
        ...descProps,
      } as Recordable;
    }

    // 渲染标签（左侧部分）
    function renderLabel({ label, labelMinWidth, labelStyle }: DescItem) {
      if (!labelStyle && !labelMinWidth) {
        return label;
      }

      const labelStyles: CSSProperties = {
        ...labelStyle,
        minWidth: `${labelMinWidth}px `,
      };
      return <div style={labelStyles}>{label}</div>;
    }

    function renderItem() {
      const { schema, data } = unref(getProps);
      return unref(schema)
        .map((item) => {
          const { render, field, span, show, contentMinWidth } = item;

          if (show && isFunction(show) && !show(data)) {
            return null;
          }

          const getContent = () => {
            const _data = unref(getProps)?.data;
            if (!_data) {
              return null;
            }
            const getField = get(_data, field);
            return isFunction(render)
              ? render(getField, _data)
              : getField ?? "";
          };

          const width = contentMinWidth;
          return (
            <ElDescriptionsItem
              label={renderLabel(item) as string}
              key={field}
              span={span}
            >
              {() => {
                if (!contentMinWidth) {
                  return getContent();
                }
                const style: CSSProperties = {
                  minWidth: `${width}px`,
                };
                return <div style={style}>{getContent()}</div>;
              }}
            </ElDescriptionsItem>
          );
        })
        .filter((item) => !!item);
    }

    const renderDesc = () => {
      const { title } = unref(getMergeProps);
      console.log("🚀 ~ setup ~ title:", title);

      return (
        <ElDescriptions {...(unref(getDescriptionsProps) as any)} >
          {renderItem()}
        </ElDescriptions>
      );
    };
    const methods: DescInstance = {
      setDescProps,
    };
    emit("register", methods);
    return () => renderDesc();
  },
});
</script>
